package base.validation;

import base.standard.constant.ErrorCode;
import base.standard.exception.SimpleException;
import org.springframework.util.StringUtils;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import java.util.Set;

/**
 * Validatior
 *
 * @description: 手工校验器
 * @author: cyj
 * @date 2020 -09-14 17:11:44
 */
public class Validator {

    /**
     * validator
     */
    private static final javax.validation.Validator VALIDATOR = Validation.buildDefaultValidatorFactory().getValidator();

    /**
     * Validate validator result
     * 校验返回ValidatorResult
     * @param <T>    parameter
     * @param object object 校验实体
     * @param groups groups 校验分组
     * @return the validator result
     * @description:
     */
    public static <T> ValidatorResult validate(T object, Class... groups) {
        Set<ConstraintViolation<T>> constraintViolations = VALIDATOR.validate(object, groups);
        ValidatorResult validatorResult = new ValidatorResult();
        validatorResult.setMessage(assembleMessage(constraintViolations));
        validatorResult.setResult(validatorResult.getMessage().isEmpty());
        return validatorResult;
    }

    /**
     * Validate as throw * GacRuntimeException
     * 校验, 成功不抛异常, 失败抛出GacRuntimeException, 由全局异常捕获, 或者业务代码捕获
     * @param <T>    parameter
     * @param object object 校验实体
     * @param groups groups 校验分组
     */
    public static <T> void validateAsThrow(T object, Class... groups) {
        Set<ConstraintViolation<T>> constraintViolations = VALIDATOR.validate(object, groups);
        String message = assembleMessage(constraintViolations);
        if (!StringUtils.isEmpty(message)) {
            throw new SimpleException(ErrorCode.VALIDATOR_ERROR, message);
        }
    }

    /**
     * Assemble message string
     * 拼接校验Validator校验结果
     * @param <T>                  parameter
     * @param constraintViolations constraint violations
     * @return the string
     * @description:
     */
    private static <T> String assembleMessage(Set<ConstraintViolation<T>> constraintViolations) {
        if (constraintViolations.isEmpty()) {
            return "";
        }
        StringBuffer message = new StringBuffer();
        constraintViolations.stream().forEach(tConstraintViolation ->
                message.append(", ").append(tConstraintViolation.getPropertyPath())
                        .append(":").append(tConstraintViolation.getMessage()));
        message.append(".");
        String messageResult = message.toString();
        return messageResult.replaceFirst(", ", "");
    }

}

